#include <xen/console.h>
#include <xen/hypercall.h>
+static DEFINE_SPINLOCK(efi_time_services_lock);
+
extern unsigned long running_on_sim;
+ struct sal_mc_params {
+ u64 param_type;
+ u64 i_or_m;
+ u64 i_or_m_val;
+ u64 timeout;
+ u64 rz_always;
+ } sal_mc_params[SAL_MC_PARAM_CPE_INT + 1];
+
+ struct sal_vectors {
+ u64 vector_type;
+ u64 handler_addr1;
+ u64 gp1;
+ u64 handler_len1;
+ u64 handler_addr2;
+ u64 gp2;
+ u64 handler_len2;
+ } sal_vectors[SAL_VECTOR_OS_BOOT_RENDEZ + 1];
+
+ struct smp_call_args_t {
+ u64 type;
+ u64 ret;
+ u64 target;
+ struct domain *domain;
+ int corrected;
+ int status;
+ void *data;
+ };
+
+ extern sal_log_record_header_t *sal_record;
+ DEFINE_SPINLOCK(sal_record_lock);
+
+ extern spinlock_t sal_queue_lock;
+
+ #define IA64_SAL_NO_INFORMATION_AVAILABLE -5
+
+ #if defined(IA64_SAL_DEBUG_INFO)
+ static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };
+
+ # define IA64_SAL_DEBUG(fmt...) printk("sal_emulator: " fmt)
+ #else
+ # define IA64_SAL_DEBUG(fmt...)
+ #endif
+
+ void get_state_info_on(void *data) {
+ struct smp_call_args_t *arg = data;
+ int flags;
+
+ spin_lock_irqsave(&sal_record_lock, flags);
+ memset(sal_record, 0, ia64_sal_get_state_info_size(arg->type));
+ arg->ret = ia64_sal_get_state_info(arg->type, (u64 *)sal_record);
+ IA64_SAL_DEBUG("SAL_GET_STATE_INFO(%s) on CPU#%d returns %ld.\n",
+ rec_name[arg->type], smp_processor_id(), arg->ret);
+ if (arg->corrected) {
+ sal_record->severity = sal_log_severity_corrected;
+ IA64_SAL_DEBUG("%s: IA64_SAL_CLEAR_STATE_INFO(SAL_INFO_TYPE_MCA)"
+ " force\n", __FUNCTION__);
+ }
+ if (arg->ret > 0) {
+ /*
+ * Save current->domain and set to local(caller) domain for
+ * xencomm_paddr_to_maddr() which calculates maddr from
+ * paddr using mpa value of current->domain.
+ */
+ struct domain *save;
+ save = current->domain;
+ current->domain = arg->domain;
+ if (xencomm_copy_to_guest((void*)arg->target,
+ sal_record, arg->ret, 0)) {
+ printk("SAL_GET_STATE_INFO can't copy to user!!!!\n");
+ arg->status = IA64_SAL_NO_INFORMATION_AVAILABLE;
+ arg->ret = 0;
+ }
+ /* Restore current->domain to saved value. */
+ current->domain = save;
+ }
+ spin_unlock_irqrestore(&sal_record_lock, flags);
+ }
+
+ void clear_state_info_on(void *data) {
+ struct smp_call_args_t *arg = data;
+
+ arg->ret = ia64_sal_clear_state_info(arg->type);
+ IA64_SAL_DEBUG("SAL_CLEAR_STATE_INFO(%s) on CPU#%d returns %ld.\n",
+ rec_name[arg->type], smp_processor_id(), arg->ret);
+
+ }
+
struct sal_ret_values
sal_emulator (long index, unsigned long in1, unsigned long in2,
unsigned long in3, unsigned long in4, unsigned long in5,